<template>
    <div class="event-modal-wrapper">
        <el-dialog :model-value="props.value" :title="dialog.title" :width="dialog.width" destroy-on-close>
            <el-form ref="ruleFormRef" :model="formData" :rules="ruleForm" label-width="110px" :disabled="isLook()">
                <el-form-item label="事件名称" prop="displayName">
                    <el-input
                        v-model="formData.displayName"
                        @input="value => (formData.displayName = value.trim())"
                        placeholder="请输入事件名称"
                        maxlength="50"
                    />
                </el-form-item>
                <el-form-item label="模型名称">
                    <el-input :value="detailData.displayName" disabled />
                </el-form-item>
                <el-form-item label="标识符">
                    <el-input disabled :value="row?.ruleName" placeholder="系统自动生" />
                </el-form-item>
                <el-form-item label="触发时机" prop="eventType">
                    <el-select
                        placeholder="请选择触发时机"
                        v-model="formData.eventType"
                        multiple
                        collapse-tags
                        collapse-tags-tooltip
                        filterable
                    >
                        <el-option v-for="(value, key) in EventType" :label="value" :key="key" :value="key" />
                    </el-select>
                </el-form-item>
                <el-form-item label="执行类型" prop="actionsExecutionType">
                    <el-radio-group v-model="formData.actionsExecutionType">
                        <el-radio v-for="(value, key) in ActionsExecutionType" :key="key" :value="key">{{
                            value
                        }}</el-radio>
                    </el-radio-group>
                </el-form-item>
                <el-form-item label="执行方式" prop="eventAction">
                    <el-select
                        placeholder="请选择执行方式"
                        v-model="formData.eventAction"
                        @change="onEventActionChange"
                        filterable
                    >
                        <el-option v-for="(value, key) in EventAction" :label="value" :key="key" :value="key" />
                    </el-select>
                </el-form-item>
                <el-form-item label="Spi实现类" prop="Spi" v-if="formData.eventAction === 'SPI'">
                    <el-select placeholder="请选择Spi实现类" v-model="formData.Spi" filterable>
                        <el-option
                            v-for="(item, i) in spiList"
                            :label="item.handlerName"
                            :key="i"
                            :value="item.handlerName"
                        />
                    </el-select>
                </el-form-item>
                <el-form-item label="Script脚本" prop="script" v-if="formData.eventAction === 'SCRIPT'">
                    <el-select placeholder="请选择Script脚本" v-model="formData.script" filterable>
                        <el-option
                            v-for="(item, i) in scriptList"
                            :label="item.scriptName"
                            :key="i"
                            :value="item.scriptNo"
                        />
                    </el-select>
                </el-form-item>
                <el-form-item
                    label="模型属性"
                    required
                    v-if="formData.eventAction === 'UPDATE_OBJECT'"
                    prop="modelAttribute"
                    style="width: 100%; margin-left: 0"
                    class="trigger-condition-form-item"
                >
                    <div ref="modelAttributeRef">
                        <ModelAttributeChoice
                            :modelDetail="detailData"
                            :defaultData="modelAttributeDefaultData"
                            ref="modelAttributeChoiceRef"
                            @add="modelAttributeAdd"
                            @del="modelAttributeDel"
                            multiple
                        >
                            <template #default="slotProps">
                                <el-select
                                    placeholder="值类型"
                                    :class="{ error: !formData.modelAttribute[slotProps.index].valueType }"
                                    style="margin-left: 10px"
                                    v-model="formData.modelAttribute[slotProps.index].valueType"
                                >
                                    <el-option
                                        v-for="(value, key) in AttrValueType"
                                        :label="value"
                                        :key="key"
                                        :value="key"
                                    />
                                </el-select>
                                <el-input
                                    v-if="attributeType(slotProps.item) === 'NUMBER'"
                                    v-model="formData.modelAttribute[slotProps.index].value"
                                    @input="
                                        value =>
                                            (formData.modelAttribute[slotProps.index].value = value.replace(
                                                /[^0-9.eE+-]/g,
                                                ''
                                            ))
                                    "
                                    :class="{ error: !formData.modelAttribute[slotProps.index].value }"
                                    placeholder="请输入默认值"
                                    maxlength="50"
                                />
                                <el-date-picker
                                    style="width: 190px; flex: 0 0 auto; margin-left: 5px"
                                    v-else-if="attributeType(slotProps.item) === 'DATE'"
                                    v-model="formData.modelAttribute[slotProps.index].value"
                                    type="datetime"
                                    value-format="YYYY-MM-DD HH:mm:ss"
                                    placeholder="请选择默认时间"
                                    :class="{ error: !formData.modelAttribute[slotProps.index].value }"
                                />
                                <el-radio-group
                                    v-else-if="attributeType(slotProps.item) === 'BOOLEAN'"
                                    v-model="formData.modelAttribute[slotProps.index].value"
                                    :class="{ error: !formData.modelAttribute[slotProps.index].value }"
                                >
                                    <el-radio :value="true">true</el-radio>
                                    <el-radio :value="false">false</el-radio>
                                </el-radio-group>
                                <el-input
                                    v-else
                                    :class="{ error: !formData.modelAttribute[slotProps.index].value }"
                                    v-model="formData.modelAttribute[slotProps.index].value"
                                    style="margin-left: 10px"
                                    placeholder="请输入更新值"
                                    maxlength="50"
                                />
                            </template>
                        </ModelAttributeChoice>
                    </div>
                </el-form-item>
                <el-form-item label="描述" style="width: 100%; margin-left: 0">
                    <el-input
                        v-model="formData.description"
                        type="textarea"
                        maxlength="200"
                        show-word-limit
                        placeholder="请输入描述"
                    />
                </el-form-item>
                <FilterCondition
                    ref="fterConditionRef"
                    :row="row"
                    conditionType="BASIC_CONDITION"
                    :modelDetail="detailData"
                ></FilterCondition>
            </el-form>
            <template #footer>
                <div class="dialog-footer">
                    <template v-if="!isLook()">
                        <el-button
                            type="primary"
                            @click="
                                () => {
                                    formData.enableStatus = true;
                                    submitForm();
                                }
                            "
                            :loading="loading"
                            >确定并启用</el-button
                        >
                        <el-button type="primary" @click="submitForm" :loading="loading">确定</el-button>
                        <el-button @click="props.close">取消</el-button>
                    </template>
                    <el-button v-else @click="props.close">关闭</el-button>
                </div>
            </template>
        </el-dialog>
    </div>
</template>
<script setup lang="ts">
import { modelBusinessService, runScriptService, runSpiService } from '@great/services';
import { ref } from 'vue';
import type { PopupBoxProps } from '@great/utils';
import { EventType, ActionsExecutionType, EventAction, AttrValueType } from '@/utils/constant';
import { useRequest } from 'vue-request';
import type { FormInstance, FormRules } from 'element-plus';
import FilterCondition from '@/components/FilterCondition.vue';
import ModelAttributeChoice from '@/components/ModelAttributeChoice.vue';

interface IProps extends PopupBoxProps {
    row?: Record<string, any>;
    detailData: Record<string, any>;
    attributeTypeList: Record<string, any>;
    callBack?: () => Promise<void>;
}

const props = defineProps<IProps>();
interface Dialog {
    title: string;
    width: number;
    detail?: Record<string, any>;
}
const dialog = reactive<Dialog>({
    title: '新建事件',
    width: 900,
    detail: undefined
});
const elementRef = useTemplateRef('fterConditionRef');
const modelAttributeRef = useTemplateRef('modelAttributeRef');
const modelAttributeChoiceRef = useTemplateRef('modelAttributeChoiceRef');
const formData = reactive<any>({
    id: undefined,
    objectName: props.detailData.objectName,
    displayName: '',
    eventType: [],
    actionsExecutionType: 'SYNC',
    eventAction: '',
    Spi: '', // {"type":"SPI","spiName":"xxxxxx"}
    script: '', // {"type":"SCRIPT","scriptName":"xxxxxxxxxxxxxxxxxxxxxxxxxx"}
    modelAttribute: [
        {
            value: '',
            valueType: ''
        }
    ],
    description: '',
    enableStatus: false, // 禁用状态，默认不启用
    basicCondition: '', // 事件执行条件定义
    execSchema: ''
});
const ruleFormRef = ref<FormInstance>();
const ruleForm = reactive<FormRules<any>>({
    displayName: [{ required: true, message: '请输入事件名称', trigger: ['blur', 'change'] }],
    eventType: [{ required: true, message: '请选择触发时机', trigger: ['blur', 'change'] }],
    actionsExecutionType: [{ required: true, message: '请选择执行类型', trigger: ['blur', 'change'] }],
    eventAction: [{ required: true, message: '请选择执行方式', trigger: ['blur', 'change'] }],
    Spi: [{ required: true, message: '请选择Spi实现类', trigger: ['blur', 'change'] }],
    script: [{ required: true, message: '请选择Script脚本', trigger: ['blur', 'change'] }],
    attributeName: [{ required: true, message: '请选择模型属性', trigger: ['blur', 'change'] }],
    modelAttribute: [
        {
            validator: (rule: any, value: any, callback: any) => {
                if (modelAttributeRef.value?.querySelector('.error')) {
                    return callback(new Error('请选择模型属性'));
                }
                return callback();
            },
            trigger: ['blur', 'change']
        }
    ]
});
const modelAttributeDefaultData = ref<any>(null);
const scriptList = ref<any>([]);
const spiList = ref<any>([]);
// 执行方式切换
const onEventActionChange = () => {
    if (formData.eventAction == 'SPI') getSpi();
    if (formData.eventAction == 'SCRIPT') getScript();
};
// 模型属性添加触发
const modelAttributeAdd = () => {
    formData.modelAttribute.push({
        value: '',
        valueType: ''
    });
};
// 模型属性删除触发
const modelAttributeDel = (index: number) => {
    formData.modelAttribute.splice(index, 1);
};
const attributeType = item => {
    let attrType = '';
    if (item.typeName) {
        attrType = props.attributeTypeList.value[item.typeName]?.persistType.toUpperCase();
    }
    return attrType;
};
// 获取Spi
const getSpi = async () => {
    if (spiList.value && spiList.value.length) return;
    const res = await runSpiService.getSpiList('EVENT_ACTION');
    spiList.value = res.data;
};
// 获取Script
const getScript = async () => {
    if (scriptList.value && scriptList.value.length) return;
    const res = await runScriptService.getScriptList({
        scriptType: 'scriptEvent'
    });
    scriptList.value = res.data;
};
// 是否为编辑
const isEdit = (par?: boolean): boolean => {
    if (par === undefined) {
        return dialog.title.includes('修改');
    } else {
        return dialog.title.includes('修改') && par;
    }
};
const isLook = () => {
    return dialog.title.includes('查看');
};
// 构建提交数据
const buildFormData = () => {
    let targetData = JSON.parse(JSON.stringify(formData));
    let execSchema: any;
    if (formData.eventAction == 'SPI') {
        execSchema = { type: formData.eventAction, spiName: formData.Spi };
    } else if (formData.eventAction == 'SCRIPT') {
        execSchema = { type: formData.eventAction, scriptName: formData.script };
    } else if (formData.eventAction == 'UPDATE_OBJECT') {
        let modelAttributeData = modelAttributeChoiceRef.value?.getModelAttribute();
        execSchema = { type: formData.eventAction, attributes: [] };
        modelAttributeData?.forEach((item, i) => {
            execSchema.attributes.push({
                displayName: item.attribute.displayName,
                attributeName: item.attribute.attributeName,
                expression: `${item.model.objectName}.${item.attribute.attributeName}`,
                typeName: item.attribute.typeName,
                valueType: formData.modelAttribute[i].valueType,
                value: formData.modelAttribute[i].value
            });
        });
    }
    delete targetData.Spi;
    delete targetData.script;
    delete targetData.modelAttribute;
    targetData.execSchema = JSON.stringify(execSchema);
    targetData.eventType = targetData.eventType.join(',');
    return targetData;
};

// 提交接口请求
const { run, loading } = useRequest(
    () => {
        return modelBusinessService.event[isEdit() ? 'update' : 'create'](buildFormData());
    },
    {
        manual: true,
        onSuccess() {
            ElNotification({
                title: isEdit() ? '修改成功！' : '新建成功！',
                type: 'success'
            });
            closeDialog();
        }
    }
);
// 表单提交
const submitForm = () => {
    ruleFormRef.value?.validate(valid => {
        if (!valid) return;
        let basicCondition = elementRef.value?.getCondition();
        formData.basicCondition = JSON.stringify(basicCondition);
        run();
    });
};
//关闭弹框
const closeDialog = () => {
    props.close();
    props.callBack?.();
};
const escapeRegExp = (str: string) => {
    return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
};
// 打开弹框
const openDialog = () => {
    if (props.row) {
        dialog.title = props.callBack ? '修改事件' : '查看事件';
        dialog.detail = JSON.parse(JSON.stringify(props.row));
        formData.id = props.row.id;
        Object.keys(formData).forEach(key => {
            if (key === 'eventType') {
                formData.eventType = props.row?.eventType ? props.row?.eventType.split(',') : [];
            } else {
                formData[key] = (props.row as any)[key];
            }
        });
        if (props.row.eventAction == 'SPI') {
            getSpi();
            if (formData.execSchema) formData.Spi = JSON.parse(formData.execSchema).spiName;
        }
        if (props.row.eventAction == 'SCRIPT') {
            getScript();
            if (formData.execSchema) formData.script = JSON.parse(formData.execSchema).scriptName;
        }
        if (props.row.eventAction == 'UPDATE_OBJECT') {
            if (formData.execSchema) {
                formData.modelAttribute = [];
                modelAttributeDefaultData.value = [];
                JSON.parse(props.row.execSchema).attributes.forEach(item => {
                    const regex = new RegExp(`\\.${escapeRegExp(item.attributeName)}$`);
                    modelAttributeDefaultData.value.push({
                        model: item.expression.replace(regex, ''),
                        typeName: item.typeName,
                        attribute: item.attributeName
                    });
                    formData.modelAttribute.push({
                        value: item.value,
                        valueType: item.valueType
                    });
                });
            } else {
                formData.modelAttribute = [
                    {
                        value: '',
                        valueType: ''
                    }
                ];
            }
        }
    }
};

const init = () => {
    openDialog();
};
init();
</script>
<style scoped lang="scss">
.event-modal-wrapper {
    .el-form {
        display: flex;
        flex-wrap: wrap;
        .el-form-item {
            width: calc((100% - 10px) / 2);
        }
        .el-form-item:nth-child(even) {
            margin-left: 10px;
        }
    }
    :deep(.trigger-condition-form-item.is-error) {
        .el-form-item__content {
            border: none;
            border-radius: 0;
            padding: 0;
        }
        .el-select__wrapper,
        .el-input__wrapper {
            box-shadow: 0 0 0 1px var(--el-border-color) inset !important;
        }

        .el-input.error {
            .el-input__wrapper {
                box-shadow: 0 0 0 1px var(--el-color-danger) inset !important;
            }
        }
        .el-select.error {
            .el-select__wrapper {
                box-shadow: 0 0 0 1px var(--el-color-danger) inset !important;
            }
        }
    }
}
</style>
